package com.rex.sample.aspect;

import com.alibaba.fastjson.JSON;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;


/**
 *
 * @ClassName: LogAspect
 * @Description: 日志记录AOP实现
 *
 */
@Aspect
@Component
public class LogAspect {

    /**
     * RpcReqAndRespLog不显示完整的json response的字符长度
     */
    public static int logRequestLenWhenNotFull = 50;

    private Logger logger = LoggerFactory.getLogger("RequestLog");
    private String requestPath = null ; // 请求地址
    private String ua;
    private Long userId = null ; // 用户名
    private Map<?,?> inputParamMap = null ; // 传入参数
    private Map<String, Object> outputParamMap = null; // 存放输出结果
    private long startTimeMillis = 0; // 开始时间
    private long endTimeMillis = 0; // 结束时间

    /**
     *
     * @Title：doBeforeInServiceLayer
     * @Description: 方法调用前触发
     *  记录开始时间
     * @author shaojian.yu
     * @date 2014年11月2日 下午4:45:53
     * @param joinPoint
     */
    @Before("execution(* com.rex.sample.controller..*.*(..))")
    public void doBeforeInServiceLayer(JoinPoint joinPoint) {
        startTimeMillis = System.currentTimeMillis(); // 记录方法开始执行的时间
    }

    /**
     *
     * @Title：doAfterInServiceLayer
     * @Description: 方法调用后触发
     *  记录结束时间
     * @author shaojian.yu
     * @date 2014年11月2日 下午4:46:21
     * @param joinPoint
     */
    @After("execution(* com.rex.sample.controller..*.*(..))")
    public void doAfterInServiceLayer(JoinPoint joinPoint) {
        endTimeMillis = System.currentTimeMillis(); // 记录方法执行完成的时间
        this.log();
    }

    /**
     *
     * @Title：doAround
     * @Description: 环绕触发
     * @author shaojian.yu
     * @date 2014年11月3日 下午1:58:45
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("execution(* com.rex.sample.controller..*.*(..))")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        /**
         * 1.获取request信息
         * 2.根据request获取session
         * 3.从session中取出登录用户信息
         */
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes)ra;
        HttpServletRequest request = sra.getRequest();
//        HttpSession session = request.getSession();
//        ua = request.geth
        // 从session中获取用户信息
//        SalesUser currentUser = (SalesUser) session.getAttribute(BaseController.CURRENT_USER_SESSION_KEY);
//
//        if(currentUser != null){
//            userId = currentUser.getId();
//        }else{
//            userId = null ;
//        }
        // 获取输入参数
        inputParamMap = request.getParameterMap();
        // 获取请求地址
        requestPath = request.getRequestURI().substring(9);
        // 执行完方法的返回值：调用proceed()方法，就会触发切入点方法执行
        outputParamMap = new HashMap<String, Object>();
        Object result = pjp.proceed();// result的值就是被拦截方法的返回值
        outputParamMap.put("result", result);

        return result;
    }



    public void log() {

        if (logger.isInfoEnabled()) {

            StringBuilder sb = new StringBuilder();
            sb.append("\"");
            sb.append(requestPath);
            sb.append("\" \"");
            if(userId != null)
                sb.append(userId);
            else
                sb.append("");
            sb.append("\" \"");
            String reqParam = JSON.toJSONString(inputParamMap);
            int len = reqParam.length();
            if (len <= logRequestLenWhenNotFull) {
                sb.append(reqParam);
            } else {
                sb.append(reqParam.substring(0, logRequestLenWhenNotFull));
                sb.append("...(");
                sb.append(len);
                sb.append(")");
            }
            sb.append("\" \"");
            sb.append(endTimeMillis - startTimeMillis).append("ms").append("\"");
            logger.info(sb.toString());
        }
    }
}
